package com.yonyou.ucf.mdf.app.controller;

import com.alibaba.fastjson.JSON;
import com.yonyou.iuap.event.model.BusinessEvent;
import com.yonyou.iuap.event.model.MQSendSuccessPO;
import com.yonyou.iuap.event.service.EventService;
import com.yonyou.ucf.mdd.common.constant.MddConstants;
import com.yonyou.ucf.mdd.ext.base.BaseController;
import com.yonyou.ucf.mdd.ext.bill.dto.BillDataDto;
import com.yonyou.ucf.mdd.ext.bill.rule.base.CommonRuleUtils;
import com.yonyou.ucf.mdd.ext.bpm.model.BpmRequestBody;
import com.yonyou.ucf.mdd.ext.bpm.service.DefaultBpmCompleteAspect;
import com.yonyou.ucf.mdd.ext.bpm.service.ProcessService;
import com.yonyou.ucf.mdd.ext.controller.Authentication;
import com.yonyou.ucf.mdd.ext.core.AppContext;
import com.yonyou.ucf.mdd.ext.i18n.utils.MddMultilingualUtil;
import com.yonyou.ucf.mdd.ext.login.util.ExtTokenUtil;
import com.yonyou.ucf.mdd.ext.model.BillContext;
import com.yonyou.ucf.mdd.ext.util.BillContextUtils;
import com.yonyou.ucf.mdd.ext.util.ResultMessage;
import com.yonyou.ucf.mdd.isv.service.ISVProcessService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.imeta.orm.base.BizObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Slf4j
@Controller
@RequestMapping("")
public class BpmController extends BaseController {
    private static final Logger logger = LoggerFactory.getLogger(BpmController.class);
    @Autowired
    ISVProcessService processService;


    @RequestMapping("/bpm/init")
    public void init(HttpServletRequest request, HttpServletResponse response) {
        try {
            processService.init();
            renderJson(response, ResultMessage.success());
        } catch (Exception e) {
            renderJson(response, ResultMessage.error(e.getMessage()));
            logger.error("初始化失败", e);
        }

    }

    @RequestMapping("/bpm/initTenant")
    public void initTenant(HttpServletRequest request, HttpServletResponse response) {
        try {
            processService.initTenant(null);
            renderJson(response, ResultMessage.success());
        } catch (Exception e) {
            renderJson(response, ResultMessage.error(e.getMessage()));
            logger.error("初始化失败", e);
        }

    }

    @RequestMapping("/bpm/registerInterface")
    public void registerInterface(HttpServletRequest request, HttpServletResponse response) {
        try {
            processService.registerInterface(false);
            renderJson(response, ResultMessage.success());
        } catch (Exception e) {
            renderJson(response, ResultMessage.error(e.getMessage()));
            logger.error("初始化失败", e);
        }

    }

    @RequestMapping("/bpm/updateRegisterInterface")
    public void updateRegisterInterface(HttpServletRequest request, HttpServletResponse response) {
        try {
            processService.registerInterface(true);
            renderJson(response, ResultMessage.success());
        } catch (Exception e) {
            renderJson(response, ResultMessage.error(e.getMessage()));
            logger.error("初始化失败", e);
        }

    }

    @RequestMapping("/bpm/startBpm")
    public void startBpm(@RequestBody BizObject bill, String billnum, HttpServletRequest request, HttpServletResponse response) {
        try {
            List<BizObject> bills = new ArrayList<>();
            bills.add(bill);
            BillContext billContext = BillContextUtils.getBillContext(billnum);
            processService.startBpm(billContext, bills);
            renderJson(response, ResultMessage.success());
        } catch (Exception e) {
            renderJson(response, ResultMessage.error(e.getMessage()));
            logger.error("初始化失败", e);
        }

    }

    @RequestMapping("/bpm/getAuditors")
    public void getAuditors(@RequestBody List<String> ids, String billnum, HttpServletRequest request, HttpServletResponse response) {
        if (CollectionUtils.isNotEmpty(ids)) {
            List<String> processBusinessKeyList = new ArrayList<>();
            for (String id : ids) {
                processBusinessKeyList.add(String.format("%s_%s", billnum, id));
            }
            try {
                List<Map> data = processService.getAuditorsNew(processBusinessKeyList, billnum);
                renderJson(response, ResultMessage.data(data));
            } catch (Exception e) {
                renderJson(response, ResultMessage.error(e.getMessage()));
                logger.error("getAuditors 失败", e);
            }
        } else {
            renderJson(response, ResultMessage.success());
        }
    }

    private static String getIdStr(BizObject bill) {
        return bill.get(MddConstants.PARAM_ID) == null ? "" : bill.get(MddConstants.PARAM_ID).toString();
    }

    @RequestMapping("/bpm/sso")
    public void sso(String billnum, HttpServletRequest request, HttpServletResponse response) {
        try {
            String url = processService.getProcessDefinition(billnum);
            renderJson(response, ResultMessage.data(url));
        } catch (Exception e) {
            renderJson(response, ResultMessage.error(e.getMessage()));
            logger.error("sso失败", e);
        }

    }

    @RequestMapping("/bpm/getProcessDefinition")
    public void getProcessDefinition(String billnum, HttpServletRequest request, HttpServletResponse response) {
        try {
            Object result = processService.getProcessDefinitionByBillnum(billnum);
            renderJson(response, ResultMessage.data(result));
        } catch (Exception e) {
            renderJson(response, ResultMessage.error(e.getMessage()));
            logger.error("getProcessDefinition失败", e);
        }

    }

    @RequestMapping("/bpm/existsProcessDefinition")
    public void existsProcessDefinition(String subId, String billnum, String transactionType, HttpServletRequest request, HttpServletResponse response) {
        try {
            BillContext billContext = new BillContext(billnum);
            billContext.setSubid(subId);
            BizObject bill = new BizObject();
            bill.set("bustype", transactionType);
            boolean b = processService.existsProcessDefinition(billContext, bill);
            renderJson(response, ResultMessage.data(b));
        } catch (Exception e) {
            renderJson(response, ResultMessage.error(e.getMessage()));
            logger.error("existsProcessDefinition失败", e);
        }

    }

    @RequestMapping("/bpm/complete")
    @Authentication(value = false)
    public void complete(@RequestBody BpmRequestBody params, HttpServletRequest request, HttpServletResponse response) {
        try {
            String res = processService.bpmComplete(params);
            try {
                executeBeforeAspect(params);
                // 发送事件，通知审批流
                BusinessEvent businessEvent = new BusinessEvent();
                businessEvent.setSourceID("MDD_AUDIT_CALLBACK");
                businessEvent.setEventType("MDD_AUDIT_CALLBACK_COMPLETE");
                try { //临时改动可能有风险 包一下异常
                    businessEvent.setTenantCode(AppContext.getYhtTenantId());
                } catch (Throwable e){
                    log.error("/bpm/complete setTenantCode error ", e);
                }

                log.info("BPM 终审回调 返回结果" + res);
                Map<String, Object> userObjMap = JSON.parseObject(res, Map.class);
                userObjMap.put("businessKey", params.getBusinessKey());
                userObjMap.put("source", params.getSource());
                userObjMap.put("userId", params.getUserId());
                userObjMap.put("tenantId", params.getTenantId());
                businessEvent.setUserObject(JSON.toJSONString(userObjMap));
                MQSendSuccessPO mqSendSuccessPO = com.yonyou.iuap.event.util.EventUtil.buildMQSendSuccessPO(businessEvent);
                EventService eventService = AppContext.getBean(EventService.class);
                eventService.saveMQSendSuccess(mqSendSuccessPO);
                executeAfterAspect(params);
            } catch (Throwable e1) {
                logger.error("complete发送事件失败", e1.getMessage());
            }
            renderJson(response, res);
        } catch (Throwable e) {
            logger.error("complete失败", e);
            renderJson(response, ResultMessage.error(e.getMessage()));
        }
    }

    private void executeBeforeAspect(BpmRequestBody params) {
        DefaultBpmCompleteAspect defaultBpmCompleteAspect = getDefaultBpmCompleteAspect();
        if (null != defaultBpmCompleteAspect) {
            try {
                String result = defaultBpmCompleteAspect.beforeBpmEventAspect(params);
                logger.info("前置执行器执行成功：{}" , result);
            } catch (Exception e) {
                logger.error("前置构造执行器执行失败");
            }
        }
    }

    private void executeAfterAspect(BpmRequestBody params) {
        DefaultBpmCompleteAspect defaultBpmCompleteAspect = getDefaultBpmCompleteAspect();
        if (null != defaultBpmCompleteAspect) {
            try {
                String result = defaultBpmCompleteAspect.afterBpmEventAspect(params);
                logger.info("前置执行器执行成功：" + result);
            } catch (Exception e) {
                logger.error("前置构造执行器执行失败");
            }
        }
    }

    private DefaultBpmCompleteAspect getDefaultBpmCompleteAspect() {
        DefaultBpmCompleteAspect defaultBpmCompleteAspect = (DefaultBpmCompleteAspect) AppContext.getBean("defaultAfterBpmCompleteService");
        if (null == defaultBpmCompleteAspect) {
            return (DefaultBpmCompleteAspect) AppContext.getBean("afterBpmCompleteService");
        }
        return defaultBpmCompleteAspect;
    }

    /**
     * 审批流提交 指派审批人查询接口
     *        请求URL ： /bpmAssign/assignCheck
     *        请求方法：  POST
     *        请求body： {"billnum":"xxx", "data":{detailData}}
     *        请求正常返回值： {"code":200,"message":"操作成功","data":{"assignInfo":{"assignInfoItems":[{"activityId":"approveUserTask_74e2e1374101407cb802aa91d0e8102f","activityName":"节点1","multiInstanceType":"parallel","participants":[{"id":"3bc83e85-0ce3-4934-bed9-7b8e60aecafd","name":"刘依铠(共享那些事,共享一号)","sortNum":0,"type":"USER","priority":50}],"usergroups":[],"depts":[],"posts":[],"dutys":[],"defaultFlow":false,"orderNumber":2147483647,"fullStaffAssign":false,"assignAble":true,"subProcess":false}],"userChange":false},"assignSingle":false,"assignAll":false,"assignAble":true}}
     *        请求异常返回值：{"code":999,"message":"异常提示信息"}
     * @param billDataDto
     * @param request
     * @param response
     */
    @PostMapping("/bpmAssign/assignCheck")
    @Authentication(value = false)
    public void assignCheck(@RequestBody BillDataDto billDataDto, HttpServletRequest request, HttpServletResponse response) {
        try {
            String billnum = billDataDto.getBillnum();
            Object data = billDataDto.getData();
            if(null == billnum){
                throw new Exception(MddMultilingualUtil.getFWMessage("P_YS_FW-PUB_MDD-BACK_0001065436", "表单编码不能为空"));
            }
           /* String token = ExtTokenUtil.getToken();
            if (StringUtils.isNotEmpty(token)){
                AppContext.getCurrentUserByReLogin(token);
            }*/
            Map<String,Object> assignCheckResult = new HashMap<>();
            BillContext billContext = BillContextUtils.getBillContext(billnum);
            if(!billContext.isSupportBpm()){
                renderJson(response, ResultMessage.data(assignCheckResult));
                return ;
            }
            if(null == data || null == billContext){
                if(logger.isWarnEnabled()){
                    logger.warn("必要参数为空直接返回：data" + data + " billContext: " + billContext);
                }
                renderJson(response, ResultMessage.data(assignCheckResult));
            }
            if(StringUtils.isNotBlank(billContext.getCardKey()) && !billnum.equals(billContext.getCardKey())){
                billContext = BillContextUtils.getBillContext(billContext.getCardKey());
            }

            BizObject bill = null;
            if(data instanceof Map){
                bill = new BizObject((Map<String, Object>) data);
            } else if(data instanceof String){
                List<BizObject> bills = CommonRuleUtils.decodeBills(billContext, billDataDto);
                if(CollectionUtils.isNotEmpty(bills)){
                    bill = bills.get(0);
                }
            }

            if(null == bill){
                logger.warn("必要参数为空直接返回：bill == null");
                renderJson(response, ResultMessage.data(assignCheckResult));
            }

            assignCheckResult = processService.assignCheck(billContext, bill);
            renderJson(response, ResultMessage.data(assignCheckResult));
        } catch (Exception e) {
            logger.error("complete失败", e);
            renderErrorJson(response, ResultMessage.error(e.getMessage()));
        }
    }
}
